3f69d8abYB1vMyD_QVDvzxy5Zscf1A TODO
3f9e7d53iC47UnlfORp9iC1vai6kWw docs/Makefile
40083bb4LVQzRqA3ABz0__pPhGNwtA docs/VBD-HOWTO.txt
-4021053fmeFrEyPHcT8JFiDpLNgtHQ docs/Xeno-1.2-HOWTO.txt
+4021053fmeFrEyPHcT8JFiDpLNgtHQ docs/Xeno-HOWTO.txt
3f9e7d60PWZJeVh5xdnk0nLUdxlqEA docs/eps/xenlogo.eps
3f9e7d63lTwQbp2fnx7yY93epWS-eQ docs/figs/dummy
3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/interface.tex
3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
+3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
-3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c
3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile
3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c
3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h
4006e65fWMwLqcocgik6wbF0Eeh0Og xen/include/xeno/rbtree.h
3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
+403a06a7H0hpHcKpAiDe5BPnaXWTlA xen/include/xeno/serial.h
3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
After selecting the kernel to boot, stand back and watch Xen boot,
closely followed by "domain 0" running the XenoLinux kernel. The boot
messages can also sent to the serial line by specifying the baud rate
-on the Xen cmdline (e.g., 'ser_baud=9600'); this can be very useful
+on the Xen cmdline (e.g., 'com1=9600,8n1'); this can be very useful
for debugging should anything important scroll off the screen. Xen's
startup messages will look quite familiar as much of the hardware
initialisation (SMP boot, apic setup) and device drivers are derived
ifname=dummy Don't use any network interface.
- ser_baud=xxx Enable serial I/O and set the baud rate (COM1)
+ com1=<baud>,DPS[,<io_base>,<irq>]
+ com2=<baud>,DPS[,<io_base>,<irq>]
+ Xen supports up to two 16550-compatible serial ports.
+ For example: 'com1=9600,8n1,0x408,5' maps COM1 to a
+ 9600-baud port, 8 data bits, no parity, 1 stop bit,
+ I/O port base 0x408, IRQ 5.
+ If the I/O base and IRQ are standard (com1:0x3f8,4;
+ com2:0x2f8,3) then they need not be specified.
+
+ console=<specifier list>
+ Specify the destination for Xen console I/O.
+ This is a comma-separated list of, for example:
+ vga: use VGA console and allow keyboard input
+ com1: use serial port com1
+ com2H: use serial port com2. Transmitted chars will
+ have the MSB set. Received chars must have
+ MSB set.
+ com2L: use serial port com2. Transmitted chars will
+ have the MSB cleared. Received chars must
+ have MSB cleared.
+ The latter two examples allow a single port to be
+ shared by two subsystems (eg. console and
+ debugger). Sharing is controlled by MSB of each
+ transmitted/received character.
+ [NB. Default for this option is 'com1,tty']
dom0_mem=xxx Set the initial amount of memory for domain0.
A typical Grub menu option might look like:
title Xen / XenoLinux 2.4.22
- kernel /boot/image.gz dom0_mem=131072 ser_baud=115200 noht
+ kernel /boot/image.gz dom0_mem=131072 com1=115200,8n1 noht
module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0
The first line specifies which Xen image to use, and what command line
+++ /dev/null
-###########################################
-Xeno HOWTO
-
-University of Cambridge Computer Laboratory
-
-http://www.cl.cam.ac.uk/netos/xen
-#############################
-
-
-Get Xeno Source Codes
-==========================
-
-The public master BK repository for the 1.2 release lives at:
-'bk://xen.bkbits.net/xeno-1.2.bk'
-
-To fetch a local copy, first download the BitKeeper tools at:
-http://www.bitmover.com/download with username 'bitkeeper' and
-password 'get bitkeeper'.
-
-Then install the tools and then run:
-# bk clone bk://xen.bkbits.net/xeno-1.2.bk
-
-Under your current directory, a new directory named 'xeno-1.2.bk' has
-been created, which contains all the source codes for Xen and
-XenoLinux.
-
-To get newest changes to the repository, run
-# cd xeno-1.2.bk
-# bk pull
-
-
-Build Xen
-=============================
-
-Hint: To see how to build Xen and all the control tools, inspect the
-tools/misc/xen-clone script in the BK repository. This script can be
-used to clone the repository and perform a full build.
-
-To build Xen manually:
-
-# cd xeno-1.2.bk/xen
-# make clean
-# make
-
-This will (should) produce a file called 'xen' in the current
-directory. This is the ELF 32-bit LSB executable file of Xen. You
-can also find a gzip version, named 'xen.gz'.
-
-To install the built files on your Xenoserver under /usr, type 'make
-install' at the root of the BK repository. You will need to be root to
-do this!
-
-Hint: There is also a 'make dist' rule which copies built files to an
-install directory just outside the BK repo; if this suits your setup,
-go for it.
-
-
-Build XenoLinux
-==============================
-
-This is a little more involved since the repository only contains a
-"sparse" tree -- this is essentially an 'overlay' on a standard linux
-kernel source tree. It contains only those files currently 'in play'
-which are either modified versions of files in the vanilla linux tree,
-or brand new files specific to XenoLinux.
-
-So, first you need a vanilla linux-2.4.24 tree, which is located at:
-http://www.kernel.org/pub/linux/kernel/v2.4
-
-Then:
- # mv linux-2.4.24.tar.gz /xeno-1.2.bk
- # cd /xeno-1.2.bk
- # tar -zxvf linux-2.4.24.tar.gz
-
-You'll find a new directory 'linux-2.4.24' which contains all
-the vanilla Linux 2.4.24 kernel source codes.
-
-Hint: You should choose the vanilla linux kernel tree that has the
-same version as the "sparse" tree.
-
-Next, you need to 'overlay' this sparse tree on the full vanilla Linux
-kernel tree:
-
- # cd /xeno-1.2.bk/xenolinux-2.4.24-sparse
- # ./mkbuildtree ../linux-2.4.24
-
-Finally, rename the buildtree since it is now a xenolinux buildtree.
-
- # cd /xeno-1.2.bk
- # mv linux-2.4.24 xenolinux-2.4.24
-
-Now that the buildtree is there, you can build the xenolinux kernel.
-The default configuration should work fine for most people (use 'make
-oldconfig') but you can customise using one of the other config tools
-if you want.
-
- # cd /xeno-1.2.bk/xenolinux-2.4.24
- # ARCH=xeno make oldconfig { or menuconfig, or xconfig, or config }
- # ARCH=xeno make dep bzImage
-
-Assuming the build works, you'll end up with
-/xeno-1.2.bk/xenolinux-2.4.24/arch/xeno/boot/xenolinux.gz. This is the
-gzip version of XenoLinux kernel image.
-
-
-Build the Domain Control Tools
-==============================
-
-Under '/xeno-1.2.bk/tools', there are three sub-directories:
-'balloon', 'xc' and 'misc', each containing
-a group of tools. You can enter any of the four sub-directories
-and type 'make' to compile the corresponding group of tools.
-Or you can type 'make' under '/xeno-1.2.bk/tools' to compile
-all the tools.
-
-In order to compile the control-interface library in 'xc' you must
-have zlib and development headers installed. Also you will need at
-least Python v2.2.
-
-'make install' in the tools directory will place executables and
-libraries in /usr/bin and /usr/lib. You will need to be root to do this!
-
-As noted earlier, 'make dist' installs files to a local 'install'
-directory just outside the BK repository. These files will then need
-to be installed manually onto the Xenoserver.
-
-The Example Scripts
-===================
-
-The scripts in tools/examples/ are generally useful for
-administering a Xen-based system. You can install them by running
-'make install' in that directory.
-
-The python scripts (*.py) are the main tools for controlling
-Xen domains.
-
-'defaults' and 'democd' are example configuration files for starting
-new domains.
-
-'xendomains' is a Sys-V style init script for starting and stopping
-Xen domains when the system boots / shuts down.
-
-These will be discussed below in more detail.
-
-
-Installation
-==============================
-
-First:
-# cp /xen-1.2.bk/xen/xen.gz /boot/xen.gz
-# cp /xen-1.2.bk/xenolinux-2.4.24/arch/xeno/boot/xenolinux.gz /boot/xenolinux.gz
-
-Second, you must have 'GNU Grub' installed. Then you need to edit
-the Grub configuration file '/boot/grub/menu.lst'.
-
-A typical Grub menu option might look like:
-
-title Xen 1.2 / XenoLinux 2.4.24
- kernel /boot/xen.gz dom0_mem=131072 ser_baud=115200 noht
- module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0
-
-The first line specifies which Xen image to use, and what command line
-arguments to pass to Xen. In this case we set the maximum amount of
-memory to allocate to domain0, and enable serial I/O at 115200 baud.
-We could also disable smp support (nosmp) or disable hyper-threading
-support (noht). If you have multiple network interface you can use
-ifname=ethXX to select which one to use. If your network card is
-unsupported, use ifname=dummy
-
-The second line specifies which XenoLinux image to use, and the
-standard linux command line arguments to pass to the kernel. In this
-case, we're configuring the root partition and stating that it should
-(initially) be mounted read-only (normal practice).
-
-The following is a list of command line arguments to pass to Xen:
-
- ignorebiostables Disable parsing of BIOS-supplied tables. This may
- help with some chipsets that aren't fully supported
- by Xen. If you specify this option then ACPI tables are
- also ignored, and SMP support is disabled.
-
- noreboot Don't reboot the machine automatically on errors.
- This is useful to catch debug output if you aren't
- catching console messages via the serial line.
-
- nosmp Disable SMP support.
- This option is implied by 'ignorebiostables'.
-
- noacpi Disable ACPI tables, which confuse Xen on some chipsets.
- This option is implied by 'ignorebiostables'.
-
- watchdog Enable NMI watchdog which can report certain failures.
-
- noht Disable Hyperthreading.
-
- ifname=ethXX Select which Ethernet interface to use.
-
- ifname=dummy Don't use any network interface.
-
- ser_baud=xxx Enable serial I/O and set the baud rate.
-
- dom0_mem=xxx Set the maximum amount of memory for domain0.
-
-
-Boot into Domain 0
-==============================
-
-Reboot your computer; After selecting the kernel to boot, stand back
-and watch Xen boot, closely followed by "domain 0" running the
-XenoLinux kernel. Depending on which root partition you have assigned
-to XenoLinux kernel in Grub configuration file, you can use the
-corresponding username / password to log in.
-
-Once logged in, it should look just like any regular linux box. All
-the usual tools and commands should work as per usual.
-
-
-Start New Domains
-==============================
-
-You must be 'root' to start new domains.
-
-Make sure you have successfully configured at least one
-physical network interface. Then:
-
-# xen_nat_enable
-# xen_read_console &
-
-When new domains are created and started, they will send output via
-UDP packets to the local virtual network. Those packets are received
-by xen_read_console running in Domain 0 and output are printed out to
-the standard output.
-
-The xc_dom_create.py program is useful for starting Xen domains.
-You can specify configuration files using the -f switch on the command
-line. The default configuration is in /etc/xc/defaults. You can
-create custom versions of this to suit your local configuration.
-
-You can override the settings in a configuration file using command
-line arguments to xc_dom_create.py. However, you may find it simplest
-to create a separate configuration file for each domain you start.
-
-When you start domains, you should be able to see XenoLinux boot
-message on standard output with each line prepended with [domain_id].
-
-
-Manage Running Domains
-==============================
-
-You can see a list of existing domains with:
-# xc_dom_control.py list
-
-In order to stop a domain, you use:
-# xc_dom_control.py stop <domain_id>
-
-To shutdown a domain cleanly use:
-# xc_dom_control.py shutdown <domain_id>
-
-To destroy a domain immediately:
-# xc_dom_control.py destroy <domain_id>
-
-There are other more advanced options, including pinning domains to
-specific CPUs and saving / resuming domains to / from disk files. To
-get more information, run the tool without any arguments:
-# xc_dom_control.py
-
-There is more information available in the Xen README files, the
-VBD-HOWTO and the contributed FAQ / HOWTO documents on the web.
-
-
-Other Control Tasks using Python
-================================
-
-A Python module 'Xc' is installed as part of the tools-install
-process. This can be imported, and an 'xc object' instantiated, to
-provide access to privileged command operations:
-
-# import Xc
-# xc = Xc.new()
-# dir(xc)
-# help(xc.domain_create)
-
-In this way you can see that the class 'xc' contains useful
-documentation for you to consult.
-
-A further module of useful routines (XenoUtil) is also installed:
-
-# import XenoUtil
-# help(XenoUtil)
-
-You can use these modules to write your own custom scripts or you can
-customise the scripts supplied in the Xen distribution.
-
-
-Automatically start / stop domains at boot / shutdown
-=====================================================
-
-A Sys-V style init script for RedHat systems is provided in
-tools/examples/xendomains. When you run 'make install' in that
-directory, it should be automatically copied to /etc/init.d/. You can
-then enable it using the chkconfig command, e.g.:
-
-# chkconfig --add xendomains
-
-By default, this will start the boot-time domains in runlevels 3, 4
-and 5. To specify a domain is to start at boot-time, place its
-configuration file (or a link to it) under /etc/xc/auto/.
-
-The script will also stop ALL domains when the system is shut down,
-even domains that it did not start originally.
-
-You can also use the "service" command (part of the RedHat standard
-distribution) to run this script manually, e.g:
-
-# service xendomains start
-
-Starts all the domains with config files under /etc/xc/auto/.
-
-# service xendomains stop
-
-Shuts down ALL running Xen domains.
--- /dev/null
+###########################################
+Xeno HOWTO
+
+University of Cambridge Computer Laboratory
+
+http://www.cl.cam.ac.uk/netos/xen
+#############################
+
+
+Get Xeno Source Codes
+==========================
+
+The public master BK repository for the 1.2 release lives at:
+'bk://xen.bkbits.net/xeno-1.2.bk'
+
+To fetch a local copy, first download the BitKeeper tools at:
+http://www.bitmover.com/download with username 'bitkeeper' and
+password 'get bitkeeper'.
+
+Then install the tools and then run:
+# bk clone bk://xen.bkbits.net/xeno-1.2.bk
+
+Under your current directory, a new directory named 'xeno-1.2.bk' has
+been created, which contains all the source codes for Xen and
+XenoLinux.
+
+To get newest changes to the repository, run
+# cd xeno-1.2.bk
+# bk pull
+
+
+Build Xen
+=============================
+
+Hint: To see how to build Xen and all the control tools, inspect the
+tools/misc/xen-clone script in the BK repository. This script can be
+used to clone the repository and perform a full build.
+
+To build Xen manually:
+
+# cd xeno-1.2.bk/xen
+# make clean
+# make
+
+This will (should) produce a file called 'xen' in the current
+directory. This is the ELF 32-bit LSB executable file of Xen. You
+can also find a gzip version, named 'xen.gz'.
+
+To install the built files on your Xenoserver under /usr, type 'make
+install' at the root of the BK repository. You will need to be root to
+do this!
+
+Hint: There is also a 'make dist' rule which copies built files to an
+install directory just outside the BK repo; if this suits your setup,
+go for it.
+
+
+Build XenoLinux
+==============================
+
+This is a little more involved since the repository only contains a
+"sparse" tree -- this is essentially an 'overlay' on a standard linux
+kernel source tree. It contains only those files currently 'in play'
+which are either modified versions of files in the vanilla linux tree,
+or brand new files specific to XenoLinux.
+
+So, first you need a vanilla linux-2.4.24 tree, which is located at:
+http://www.kernel.org/pub/linux/kernel/v2.4
+
+Then:
+ # mv linux-2.4.24.tar.gz /xeno-1.2.bk
+ # cd /xeno-1.2.bk
+ # tar -zxvf linux-2.4.24.tar.gz
+
+You'll find a new directory 'linux-2.4.24' which contains all
+the vanilla Linux 2.4.24 kernel source codes.
+
+Hint: You should choose the vanilla linux kernel tree that has the
+same version as the "sparse" tree.
+
+Next, you need to 'overlay' this sparse tree on the full vanilla Linux
+kernel tree:
+
+ # cd /xeno-1.2.bk/xenolinux-2.4.24-sparse
+ # ./mkbuildtree ../linux-2.4.24
+
+Finally, rename the buildtree since it is now a xenolinux buildtree.
+
+ # cd /xeno-1.2.bk
+ # mv linux-2.4.24 xenolinux-2.4.24
+
+Now that the buildtree is there, you can build the xenolinux kernel.
+The default configuration should work fine for most people (use 'make
+oldconfig') but you can customise using one of the other config tools
+if you want.
+
+ # cd /xeno-1.2.bk/xenolinux-2.4.24
+ # ARCH=xeno make oldconfig { or menuconfig, or xconfig, or config }
+ # ARCH=xeno make dep bzImage
+
+Assuming the build works, you'll end up with
+/xeno-1.2.bk/xenolinux-2.4.24/arch/xeno/boot/xenolinux.gz. This is the
+gzip version of XenoLinux kernel image.
+
+
+Build the Domain Control Tools
+==============================
+
+Under '/xeno-1.2.bk/tools', there are three sub-directories:
+'balloon', 'xc' and 'misc', each containing
+a group of tools. You can enter any of the four sub-directories
+and type 'make' to compile the corresponding group of tools.
+Or you can type 'make' under '/xeno-1.2.bk/tools' to compile
+all the tools.
+
+In order to compile the control-interface library in 'xc' you must
+have zlib and development headers installed. Also you will need at
+least Python v2.2.
+
+'make install' in the tools directory will place executables and
+libraries in /usr/bin and /usr/lib. You will need to be root to do this!
+
+As noted earlier, 'make dist' installs files to a local 'install'
+directory just outside the BK repository. These files will then need
+to be installed manually onto the Xenoserver.
+
+The Example Scripts
+===================
+
+The scripts in tools/examples/ are generally useful for
+administering a Xen-based system. You can install them by running
+'make install' in that directory.
+
+The python scripts (*.py) are the main tools for controlling
+Xen domains.
+
+'defaults' and 'democd' are example configuration files for starting
+new domains.
+
+'xendomains' is a Sys-V style init script for starting and stopping
+Xen domains when the system boots / shuts down.
+
+These will be discussed below in more detail.
+
+
+Installation
+==============================
+
+First:
+# cp /xen-1.2.bk/xen/xen.gz /boot/xen.gz
+# cp /xen-1.2.bk/xenolinux-2.4.24/arch/xeno/boot/xenolinux.gz /boot/xenolinux.gz
+
+Second, you must have 'GNU Grub' installed. Then you need to edit
+the Grub configuration file '/boot/grub/menu.lst'.
+
+A typical Grub menu option might look like:
+
+title Xen 1.2 / XenoLinux 2.4.24
+ kernel /boot/xen.gz dom0_mem=131072 com1=115200,8n1 noht
+ module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0
+
+The first line specifies which Xen image to use, and what command line
+arguments to pass to Xen. In this case we set the maximum amount of
+memory to allocate to domain0, and enable serial I/O at 115200 baud.
+We could also disable smp support (nosmp) or disable hyper-threading
+support (noht). If you have multiple network interface you can use
+ifname=ethXX to select which one to use. If your network card is
+unsupported, use ifname=dummy
+
+The second line specifies which XenoLinux image to use, and the
+standard linux command line arguments to pass to the kernel. In this
+case, we're configuring the root partition and stating that it should
+(initially) be mounted read-only (normal practice).
+
+The following is a list of command line arguments to pass to Xen:
+
+ ignorebiostables Disable parsing of BIOS-supplied tables. This may
+ help with some chipsets that aren't fully supported
+ by Xen. If you specify this option then ACPI tables are
+ also ignored, and SMP support is disabled.
+
+ noreboot Don't reboot the machine automatically on errors.
+ This is useful to catch debug output if you aren't
+ catching console messages via the serial line.
+
+ nosmp Disable SMP support.
+ This option is implied by 'ignorebiostables'.
+
+ noacpi Disable ACPI tables, which confuse Xen on some chipsets.
+ This option is implied by 'ignorebiostables'.
+
+ watchdog Enable NMI watchdog which can report certain failures.
+
+ noht Disable Hyperthreading.
+
+ ifname=ethXX Select which Ethernet interface to use.
+
+ ifname=dummy Don't use any network interface.
+
+ com1=<baud>,DPS[,<io_base>,<irq>]
+ com2=<baud>,DPS[,<io_base>,<irq>]
+ Xen supports up to two 16550-compatible serial ports.
+ For example: 'com1=9600,8n1,0x408,5' maps COM1 to a
+ 9600-baud port, 8 data bits, no parity, 1 stop bit,
+ I/O port base 0x408, IRQ 5.
+ If the I/O base and IRQ are standard (com1:0x3f8,4;
+ com2:0x2f8,3) then they need not be specified.
+
+ console=<specifier list>
+ Specify the destination for Xen console I/O.
+ This is a comma-separated list of, for example:
+ vga: use VGA console and allow keyboard input
+ com1: use serial port com1
+ com2H: use serial port com2. Transmitted chars will
+ have the MSB set. Received chars must have
+ MSB set.
+ com2L: use serial port com2. Transmitted chars will
+ have the MSB cleared. Received chars must
+ have MSB cleared.
+ The latter two examples allow a single port to be
+ shared by two subsystems (eg. console and
+ debugger). Sharing is controlled by MSB of each
+ transmitted/received character.
+ [NB. Default for this option is 'com1,tty']
+
+ dom0_mem=xxx Set the maximum amount of memory for domain0.
+
+
+Boot into Domain 0
+==============================
+
+Reboot your computer; After selecting the kernel to boot, stand back
+and watch Xen boot, closely followed by "domain 0" running the
+XenoLinux kernel. Depending on which root partition you have assigned
+to XenoLinux kernel in Grub configuration file, you can use the
+corresponding username / password to log in.
+
+Once logged in, it should look just like any regular linux box. All
+the usual tools and commands should work as per usual.
+
+
+Start New Domains
+==============================
+
+You must be 'root' to start new domains.
+
+Make sure you have successfully configured at least one
+physical network interface. Then:
+
+# xen_nat_enable
+# xen_read_console &
+
+When new domains are created and started, they will send output via
+UDP packets to the local virtual network. Those packets are received
+by xen_read_console running in Domain 0 and output are printed out to
+the standard output.
+
+The xc_dom_create.py program is useful for starting Xen domains.
+You can specify configuration files using the -f switch on the command
+line. The default configuration is in /etc/xc/defaults. You can
+create custom versions of this to suit your local configuration.
+
+You can override the settings in a configuration file using command
+line arguments to xc_dom_create.py. However, you may find it simplest
+to create a separate configuration file for each domain you start.
+
+When you start domains, you should be able to see XenoLinux boot
+message on standard output with each line prepended with [domain_id].
+
+
+Manage Running Domains
+==============================
+
+You can see a list of existing domains with:
+# xc_dom_control.py list
+
+In order to stop a domain, you use:
+# xc_dom_control.py stop <domain_id>
+
+To shutdown a domain cleanly use:
+# xc_dom_control.py shutdown <domain_id>
+
+To destroy a domain immediately:
+# xc_dom_control.py destroy <domain_id>
+
+There are other more advanced options, including pinning domains to
+specific CPUs and saving / resuming domains to / from disk files. To
+get more information, run the tool without any arguments:
+# xc_dom_control.py
+
+There is more information available in the Xen README files, the
+VBD-HOWTO and the contributed FAQ / HOWTO documents on the web.
+
+
+Other Control Tasks using Python
+================================
+
+A Python module 'Xc' is installed as part of the tools-install
+process. This can be imported, and an 'xc object' instantiated, to
+provide access to privileged command operations:
+
+# import Xc
+# xc = Xc.new()
+# dir(xc)
+# help(xc.domain_create)
+
+In this way you can see that the class 'xc' contains useful
+documentation for you to consult.
+
+A further module of useful routines (XenoUtil) is also installed:
+
+# import XenoUtil
+# help(XenoUtil)
+
+You can use these modules to write your own custom scripts or you can
+customise the scripts supplied in the Xen distribution.
+
+
+Automatically start / stop domains at boot / shutdown
+=====================================================
+
+A Sys-V style init script for RedHat systems is provided in
+tools/examples/xendomains. When you run 'make install' in that
+directory, it should be automatically copied to /etc/init.d/. You can
+then enable it using the chkconfig command, e.g.:
+
+# chkconfig --add xendomains
+
+By default, this will start the boot-time domains in runlevels 3, 4
+and 5. To specify a domain is to start at boot-time, place its
+configuration file (or a link to it) under /etc/xc/auto/.
+
+The script will also stop ALL domains when the system is shut down,
+even domains that it did not start originally.
+
+You can also use the "service" command (part of the RedHat standard
+distribution) to run this script manually, e.g:
+
+# service xendomains start
+
+Starts all the domains with config files under /etc/xc/auto/.
+
+# service xendomains stop
+
+Shuts down ALL running Xen domains.
pushl $int_msg
call SYMBOL_NAME(printf)
1: jmp 1b
- pop %eax
- popl %ds
- popl %es
- pop %edx
- pop %ecx
- pop %eax
- iret
-
bad_cpu_msg:
.asciz "Bad CPU type. Need P6+."
ALIGN
bad_cpu:
-/* NB. We assume the UART is set up correctly. */
- mov $bad_cpu_msg,%esi
-1: lodsb
- test %al,%al
- je 1f
- push %eax
- call putchar_serial
- add $4,%esp
- jmp 1b
+ pushl $bad_cpu_msg
+ call SYMBOL_NAME(printf)
1: jmp 1b
-
/*** STACK LOCATION ***/
{
extern spinlock_t console_lock;
extern void die(const char * str, struct pt_regs * regs, long err);
- extern void putchar_serial(unsigned char c);
int sum, cpu = smp_processor_id();
#include <asm/apic.h>
#include <asm/pdb.h>
#include <xeno/list.h>
+#include <xeno/serial.h>
#define BUFMAX 400
static int pdb_stepping = 0;
void pdb_put_packet (unsigned char *buffer, int ack);
-void pdb_put_char (u_char c);
-u_char pdb_get_char ();
+
+static int pdb_initialized = 0;
+static int pdb_serhnd = -1;
+
+#define RX_SIZE 32
+#define RX_MASK(_i) ((_i)&(RX_SIZE-1))
+static unsigned int rx_cons = 0, rx_prod = 0;
+static unsigned char rx_ring[RX_RING_SIZE];
+
+static inline void pdb_put_char(unsigned char c)
+{
+ serial_putc(pdb_serhnd, c);
+}
+
+static inline unsigned char pdb_get_char(void)
+{
+ while ( rx_cons == rx_prod )
+ barrier();
+ return rx_ring[RX_MASK(rx_cons++)];
+}
+
+static void pdb_rx_char(unsigned char c, struct pt_regs *regs)
+{
+ if ( (rx_prod - rx_cons) != RX_SIZE )
+ rx_ring[RX_MASK(rx_prod++)] = c;
+}
static volatile int mem_err = 0;
void set_mem_err (void) /* NOT USED YET... */
void breakpoint(void);
-int pdb_initialized = 0;
-int pdb_high_bit = 1;
-
-void pdb_put_char (u_char c)
-{
- extern void debug_putchar(u_char);
- u_char cc = pdb_high_bit ? c | 0x80 : c;
- debug_putchar(cc);
-}
-
-u_char pdb_get_char ()
-{
- extern u_char debug_getchar();
- u_char cc = debug_getchar();
- return cc & 0x7f;
-}
-
/* send the packet in buffer. */
void pdb_put_packet (unsigned char *buffer, int ack)
{
void initialize_pdb()
{
extern char opt_pdb[];
- int pdb_com_port;
/* Certain state must be initialised even when PDB will not be used. */
breakpoints.address = 0;
INIT_LIST_HEAD(&breakpoints.list);
pdb_stepping = 0;
- if ( strncmp(opt_pdb, "com", 3) == 0 )
- {
- extern void debug_set_com_port(int port);
+ if ( strcmp(opt_pdb, "none") == 0 )
+ return;
- pdb_com_port = opt_pdb[3] - '0'; /* error checking ? */
- debug_set_com_port(pdb_com_port);
- pdb_high_bit = opt_pdb[4] == 'H' ? 1 : 0;
- }
- else
+ if ( (pdb_serhnd = parse_serial_handle(opt_pdb)) == -1 )
{
- if ( strcmp(opt_pdb, "none") != 0 )
- printk ("pdb: unknown option\n");
+ printk("Failed to initialise PDB on port %s\n", opt_pdb);
return;
}
- printk("Initializing pervasive debugger (PDB) on serial port %d %s\n",
- pdb_com_port, pdb_high_bit ? "(high bit enabled)" : "");
+ serial_set_rx_handler(pdb_serhnd, pdb_rx_char);
+
+ printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb);
- /* ack any spurrious gdb packets */
- pdb_put_char ('+');
+ /* Acknowledge any spurious GDB packets. */
+ serial_putc(pdb_serhnd, '+');
- /* serial console */
add_key_handler('D', pdb_key_pressed, "enter pervasive debugger");
pdb_initialized = 1;
#include <xeno/lib.h>
#include <xeno/sched.h>
#include <xeno/pci.h>
+#include <xeno/serial.h>
#include <asm/bitops.h>
#include <asm/smp.h>
#include <asm/processor.h>
extern void net_init(void);
extern void initialize_block_io(void);
extern void initialize_keytable();
- extern void initialize_serial(void);
extern void initialize_keyboard(void);
extern int opt_nosmp, opt_watchdog, opt_noacpi, opt_ignorebiostables;
extern int do_timer_lists_from_pit;
initialize_keytable(); /* call back handling for key codes */
+ serial_init_stage2();
+ initialize_keyboard(); /* setup keyboard (also for debugging) */
+ initialize_pdb(); /* pervasive debugger */
+
if ( !cpu_has_apic )
{
do_timer_lists_from_pit = 1;
pci_init();
#endif
do_initcalls();
- initialize_serial(); /* setup serial 'driver' (for debugging) */
- initialize_keyboard(); /* setup keyboard (also for debugging) */
- initialize_pdb(); /* pervasive debugger */
-
if ( !setup_network_devices() )
panic("Must have a network device!\n");
net_init(); /* initializes virtual network system. */
}
*dst = '\0';
- /* If this guy's getting the console we'd better let go. */
- if ( CONSOLE_ISOWNER(p) )
- opt_console = 0;
+ /* HACK: Give up the VGA console iff the Xenolinux DOM0 wants it. */
+ if ( strstr(cmdline, "tty0") != NULL )
+ vgacon_enabled = 0;
/* Reinstate the caller's page tables. */
write_cr3_counted(pagetable_val(current->mm.pagetable));
#include <asm/domain_page.h>
#include <xeno/console.h>
#include <xeno/net_headers.h>
+#include <xeno/serial.h>
kmem_cache_t *task_struct_cachep;
static int xpos, ypos;
-static volatile unsigned char *video;
+static unsigned char *video = __va(0xB8000);
+
+int sercon_handle = -1;
+int vgacon_enabled = 0;
spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
unsigned long type; /* type of memory segment */
};
-void init_vga(void);
-void init_serial(void);
+static void init_vga(void);
void start_of_day(void);
-/* opt_console: If true, Xen sends logging to the VGA console. */
-int opt_console = 1;
+/* opt_console: comma-separated list of console outputs. */
+unsigned char opt_console[30] = "com1,vga";
/* opt_ser_baud: Baud rate at which logging is sent to COM1. */
/* NB. Default (0) means that serial I/O is disabled. */
+/* NB2. THIS OPTION IS DEPRECATED!! */
unsigned int opt_ser_baud = 0;
+/* opt_com[12]: Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
+unsigned char opt_com1[30] = "", opt_com2[30] = "";
/* opt_dom0_mem: Kilobytes of memory allocated to domain 0. */
unsigned int opt_dom0_mem = 16000;
/* opt_ifname: Name of physical network interface to use. */
enum { OPT_IP, OPT_STR, OPT_UINT, OPT_BOOL } type;
void *var;
} opts[] = {
- { "console", OPT_UINT, &opt_console },
+ { "console", OPT_STR, &opt_console },
{ "ser_baud", OPT_UINT, &opt_ser_baud },
+ { "com1", OPT_STR, &opt_com1 },
+ { "com2", OPT_STR, &opt_com2 },
{ "dom0_mem", OPT_UINT, &opt_dom0_mem },
{ "ifname", OPT_STR, &opt_ifname },
{ "noht", OPT_BOOL, &opt_noht },
};
-void cmain (unsigned long magic, multiboot_info_t *mbi)
+void cmain(unsigned long magic, multiboot_info_t *mbi)
{
struct task_struct *new_dom;
dom0_createdomain_t dom0_params;
unsigned long max_page;
- unsigned char *cmdline;
+ unsigned char *cmdline, *p;
module_t *mod;
int i;
- /*
- * Note that serial output cannot be done properly until after
- * command-line arguments have been parsed, and the required baud rate is
- * known. Any messages before that will be output using the settings of
- * the bootloader, for example.
- */
-
- if ( magic != MULTIBOOT_BOOTLOADER_MAGIC )
- {
- init_vga();
- cls();
- printk("Invalid magic number: 0x%x\n", (unsigned)magic);
- for ( ; ; ) ;
- }
-
- /* Parse the command line. */
+ /* Parse the command-line options. */
cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL);
if ( cmdline != NULL )
{
}
}
- init_serial();
+ /* Backward compatibility with deprecated 'ser_baud=' cmdline option. */
+ if ( opt_ser_baud != 0 )
+ sprintf(opt_com1, "%u,8n1", opt_ser_baud);
+
+ /* We initialise the serial devices very early so we can get debugging. */
+ serial_init_stage1();
+
+ /* Where should console output go? */
+ for ( p = opt_console; p != NULL; p = strchr(p, ',') )
+ {
+ if ( *p == ',' )
+ p++;
+ if ( strncmp(p, "com", 3) == 0 )
+ sercon_handle = parse_serial_handle(p);
+ else if ( strncmp(p, "vga", 3) == 0 )
+ vgacon_enabled = 1;
+ }
+
+ /* Set up VGA console output, if it was enabled. */
init_vga();
- cls();
+ /* HELLO WORLD --- start-of-day banner text. */
printk(XEN_BANNER);
printk(" http://www.cl.cam.ac.uk/netos/xen\n");
printk(" University of Cambridge Computer Laboratory\n\n");
XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
XEN_COMPILER, XEN_COMPILE_DATE);
+ if ( opt_ser_baud != 0 )
+ printk("**WARNING**: Xen option 'ser_baud=' is deprecated! "
+ "Use 'com1=' instead.\n");
+
+ if ( magic != MULTIBOOT_BOOTLOADER_MAGIC )
+ {
+ printk("FATAL ERROR: Invalid magic number: 0x%08lx\n", magic);
+ for ( ; ; ) ;
+ }
+
/* We require memory and module information. */
if ( (mbi->flags & 9) != 9 )
{
}
-#define SERIAL_BASE 0x3f8
-#define RX_BUF 0
-#define TX_HOLD 0
-#define INT_ENABLE 1
-#define INT_IDENT 2
-#define DATA_FORMAT 3
-#define LINE_CTL 4
-#define LINE_STATUS 5
-#define LINE_IN 6
-#define DIVISOR_LO 0
-#define DIVISOR_HI 1
-
-void init_serial(void)
-{
- if ( !SERIAL_ENABLED )
- return;
-
- /* 'opt_ser_baud' baud, no parity, 1 stop bit, 8 data bits. */
- outb(0x83, SERIAL_BASE+DATA_FORMAT);
- outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO);
- outb(0, SERIAL_BASE+DIVISOR_HI);
- outb(0x03, SERIAL_BASE+DATA_FORMAT);
-
- /* DTR and RTS should both be high, to keep other end happy. */
- outb(0x02, SERIAL_BASE+LINE_CTL);
-
- /* No interrupts. */
- outb(0x00, SERIAL_BASE+INT_ENABLE);
-}
-
-
-#ifdef CONFIG_OUTPUT_SERIAL
-void putchar_serial(unsigned char c)
-{
- if ( !SERIAL_ENABLED )
- return;
- if ( c == '\n' ) putchar_serial('\r');
- while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier();
- outb(c, SERIAL_BASE+TX_HOLD);
-}
-#else
-void putchar_serial(unsigned char c) {}
-#endif
-
-
-#ifdef CONFIG_OUTPUT_CONSOLE
-
/* VGA text (mode 3) definitions. */
#define COLUMNS 80
#define LINES 25
#define ATTRIBUTE 7
-#define VIDEO __va(0xB8000)
-int detect_video(void *video_base)
+/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
+static void cls(void)
+{
+ memset(video, 0, COLUMNS * LINES * 2);
+ xpos = ypos = 0;
+ outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
+}
+
+static int detect_video(void *video_base)
{
volatile u16 *p = (volatile u16 *)video_base;
u16 saved1 = p[0], saved2 = p[1];
return video_found;
}
-int detect_vga(void)
+static int detect_vga(void)
{
/*
* Look at a number of well-known locations. Even if video is not at
}
/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
-void init_vga(void)
+static void init_vga(void)
{
/* The following VGA state was saved from a chip in text mode 3. */
static unsigned char regs[] = {
int i, j = 0;
volatile unsigned char tmp;
- if ( !opt_console )
+ if ( !vgacon_enabled )
return;
if ( !detect_vga() )
{
printk("No VGA adaptor detected!\n");
- opt_console = 0;
+ vgacon_enabled = 0;
return;
}
tmp = inb(0x3da);
outb(0x20, 0x3c0);
-}
-
-
-/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
-void cls(void)
-{
- int i;
- if ( !opt_console )
- return;
-
- video = (unsigned char *) VIDEO;
-
- for (i = 0; i < COLUMNS * LINES * 2; i++)
- *(video + i) = 0;
-
- xpos = 0;
- ypos = 0;
-
- outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
+ cls();
}
}
-void putchar_console(int c)
+static void putchar_console(int c)
{
- if ( !opt_console )
+ if ( !vgacon_enabled )
return;
if ( c == '\n' )
}
else
{
- *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
- *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
-
- xpos++;
- if (xpos >= COLUMNS)
+ video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF;
+ video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
+ if ( ++xpos >= COLUMNS )
put_newline();
}
}
-#else
-
-void init_vga(void) {}
-void cls(void) {}
-void putchar_console(int c) {}
-
-#endif
-
-#ifdef CONFIG_OUTPUT_CONSOLE_RING
void putchar_console_ring(int c)
{
- if (console_ring.len < CONSOLE_RING_SIZE)
+ if ( console_ring.len < CONSOLE_RING_SIZE )
console_ring.buf[console_ring.len++] = (char)c;
}
-#else
-
-void putchar_console_ring(int c) {}
-
-#endif
-
-
-static void putchar(int c)
-{
- if ( (c != '\n') && ((c < 32) || (c > 126)) ) return;
- putchar_serial(c);
- putchar_console(c);
- putchar_console_ring(c);
-}
-
static inline void __putstr(const char *str)
{
- while ( *str ) putchar(*str++);
+ int c;
+ serial_puts(sercon_handle, str);
+ while ( (c = *str++) != '\0' )
+ {
+ putchar_console(c);
+ putchar_console_ring(c);
+ }
}
-void printf (const char *fmt, ...)
+void printf(const char *fmt, ...)
{
va_list args;
char buf[128];
}
spin_lock_irqsave(&console_lock, flags);
- while ( *p ) putchar(*p++);
+ __putstr(p);
spin_unlock_irqrestore(&console_lock, flags);
}
{
#define SIZEOF_BUF 256
unsigned char safe_str[SIZEOF_BUF+1];
- unsigned char exported_str[SIZEOF_BUF+2];
- unsigned char dom_id[5];
+ unsigned char single_line[SIZEOF_BUF+2];
+ unsigned char line_header[30];
unsigned char *p;
+ unsigned char c;
unsigned long flags;
- int j;
+ int j;
if ( count == 0 )
return 0;
return -EFAULT;
safe_str[count] = '\0';
+ sprintf(line_header, "DOM%llu: ", current->domain);
+
p = safe_str;
while ( *p != '\0' )
{
j = 0;
- spin_lock_irqsave(&console_lock, flags);
-
- __putstr("DOM");
- sprintf(dom_id, "%llu", current->domain);
- __putstr(dom_id);
- __putstr(": ");
-
- while ( (*p != '\0') && (*p != '\n') )
+ while ( (c = *p++) != '\0' )
{
- exported_str[j++] = *p;
- putchar(*p);
- p++;
+ if ( c == '\n' )
+ break;
+ if ( (c < 32) || (c > 126) )
+ continue;
+ single_line[j++] = c;
}
- if ( *p == '\n' )
- p++;
+ single_line[j++] = '\n';
+ single_line[j++] = '\0';
- putchar('\n');
-
+ spin_lock_irqsave(&console_lock, flags);
+ __putstr(line_header);
+ __putstr(single_line);
spin_unlock_irqrestore(&console_lock, flags);
if ( current->domain != 0 )
- {
- exported_str[j++] = '\n';
- exported_str[j++] = '\0';
- console_export(exported_str, j);
- }
+ console_export(single_line, j);
}
return 0;
#include <xeno/keyhandler.h>
#include <xeno/reboot.h>
#include <xeno/event.h>
+#include <xeno/console.h>
+#include <xeno/serial.h>
#define KEY_MAX 256
#define STR_MAX 64
int i;
char *str;
- if(key_table[key].handler != NULL)
+ if ( key_table[key].handler != NULL )
printk("Warning: overwriting handler for key 0x%x\n", key);
key_table[key].handler = handler;
str = key_table[key].desc;
- for(i = 0; i < STR_MAX; i++) {
- if(*desc)
+ for ( i = 0; i < STR_MAX; i++ )
+ {
+ if ( *desc != '\0' )
*str++ = *desc++;
- else break;
+ else
+ break;
}
- if (i == STR_MAX)
+ if ( i == STR_MAX )
key_table[key].desc[STR_MAX-1] = '\0';
-
- return;
}
key_handler *get_key_handler(u_char key)
return key_table[key].handler;
}
+static void serial_rx(unsigned char c, struct pt_regs *regs)
+{
+ key_handler *handler;
+ if ( (handler = get_key_handler(c)) != NULL )
+ (*handler)(c, NULL, regs);
+}
static void show_handlers(u_char key, void *dev_id, struct pt_regs *regs)
{
int i;
printk("'%c' pressed -> showing installed handlers\n", key);
- for(i=0; i < KEY_MAX; i++)
- if(key_table[i].handler)
+ for ( i = 0; i < KEY_MAX; i++ )
+ if ( key_table[i].handler != NULL )
printk(" key '%c' (ascii '%02x') => %s\n",
(i<33 || i>126)?(' '):(i),i,
key_table[i].desc);
- return;
}
static void dump_registers(u_char key, void *dev_id, struct pt_regs *regs)
{
extern void show_registers(struct pt_regs *regs);
-
printk("'%c' pressed -> dumping registers\n", key);
show_registers(regs);
- return;
}
static void halt_machine(u_char key, void *dev_id, struct pt_regs *regs)
{
printk("'%c' pressed -> rebooting machine\n", key);
machine_restart(NULL);
- return;
}
static void kill_dom0(u_char key, void *dev_id, struct pt_regs *regs)
{
printk("'%c' pressed -> gracefully rebooting machine\n", key);
kill_other_domain(0, 0);
- return;
}
#endif
-void initialize_keytable()
+void initialize_keytable(void)
{
int i;
/* first initialize key handler table */
- for(i = 0; i < KEY_MAX; i++)
+ for ( i = 0; i < KEY_MAX; i++ )
key_table[i].handler = (key_handler *)NULL;
/* setup own handlers */
add_key_handler('m', reaudit_pages, "re-audit pages");
add_key_handler('M', audit_all_pages, "audit all pages");
#endif
+
+ serial_set_rx_handler(sercon_handle, serial_rx);
}
#include <asm/domain_page.h>
#ifndef NDEBUG
-#define MEM_LOG(_f, _a...) \
+#define MEM_LOG(_f, _a...) \
printk("DOM%llu: (file=memory.c, line=%d) " _f "\n", \
- current->domain, __LINE__, ## _a )
+ current->domain , __LINE__ , ## _a )
#else
#define MEM_LOG(_f, _a...) ((void)0)
#endif
--- /dev/null
+/******************************************************************************
+ * serial.c
+ *
+ * Driver for 16550-series UARTs. This driver is to be kept within Xen as
+ * it permits debugging of seriously-toasted machines (e.g., in situations
+ * where a device driver within a guest OS would be inaccessible).
+ *
+ * Copyright (c) 2003-2004, K A Fraser
+ */
+
+#include <asm-i386/io.h>
+#include <xeno/sched.h>
+#include <xeno/keyhandler.h>
+#include <xeno/reboot.h>
+#include <xeno/irq.h>
+#include <xeno/serial.h>
+#include <asm/pdb.h>
+
+/* Register offsets */
+#define RBR 0x00 /* receive buffer */
+#define THR 0x00 /* transmit holding */
+#define IER 0x01 /* interrupt enable */
+#define IIR 0x02 /* interrupt identity */
+#define FCR 0x02 /* FIFO control */
+#define LCR 0x03 /* line control */
+#define MCR 0x04 /* Modem control */
+#define LSR 0x05 /* line status */
+#define MSR 0x06 /* Modem status */
+#define DLL 0x00 /* divisor latch (ls) ( DLAB=1) */
+#define DLM 0x01 /* divisor latch (ms) ( DLAB=1) */
+
+/* Interrupt Enable Register */
+#define IER_ERDAI 0x01 /* rx data recv'd */
+#define IER_ETHREI 0x02 /* tx reg. empty */
+#define IER_ELSI 0x04 /* rx line status */
+#define IER_EMSI 0x08 /* MODEM status */
+
+/* FIFO control register */
+#define FCR_ENABLE 0x01 /* enable FIFO */
+#define FCR_CLRX 0x02 /* clear Rx FIFO */
+#define FCR_CLTX 0x04 /* clear Tx FIFO */
+#define FCR_DMA 0x10 /* enter DMA mode */
+#define FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */
+#define FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */
+#define FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
+#define FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */
+
+/* Line control register */
+#define LCR_DLAB 0x80 /* Divisor Latch Access */
+
+/* Modem Control Register */
+#define MCR_DTR 0x01 /* Data Terminal Ready */
+#define MCR_RTS 0x02 /* Request to Send */
+#define MCR_OUT2 0x08 /* OUT2: interrupt mask */
+
+/* Line Status Register */
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit hold reg empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+/* These parity settings can be ORed directly into the LCR. */
+#define PARITY_NONE (0<<3)
+#define PARITY_ODD (1<<3)
+#define PARITY_EVEN (3<<3)
+#define PARITY_MARK (5<<3)
+#define PARITY_SPACE (7<<3)
+
+typedef struct {
+ int baud, data_bits, parity, stop_bits, io_base, irq;
+ serial_rx_fn rx_lo, rx_hi, rx;
+ spinlock_t lock;
+} uart_t;
+
+static uart_t com[2] = {
+ { 0, 0, 0, 0, 0x3f8, 4,
+ NULL, NULL, NULL,
+ SPIN_LOCK_UNLOCKED },
+ { 0, 0, 0, 0, 0x2f8, 3,
+ NULL, NULL, NULL,
+ SPIN_LOCK_UNLOCKED }
+};
+
+#define UART_ENABLED(_u) ((_u)->baud != 0)
+#define DISABLE_UART(_u) ((_u)->baud = 0)
+
+
+/***********************
+ * PRIVATE FUNCTIONS
+ */
+
+static void uart_rx(uart_t *uart, struct pt_regs *regs)
+{
+ unsigned char c;
+
+ if ( !UART_ENABLED(uart) )
+ return;
+
+ /*
+ * No need for the uart spinlock here. Only the uart's own interrupt
+ * handler will read from the RBR and the handler isn't reentrant.
+ */
+ while ( inb(uart->io_base + LSR) & LSR_DR )
+ {
+ c = inb(uart->io_base + RBR);
+ if ( uart->rx != NULL )
+ uart->rx(c, regs);
+ else if ( (c & 0x80) && (uart->rx_hi != NULL) )
+ uart->rx_hi(c&0x7f, regs);
+ else if ( !(c & 0x80) && (uart->rx_lo != NULL) )
+ uart->rx_lo(c&0x7f, regs);
+ }
+}
+
+static void serial_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ uart_rx((uart_t *)dev_id, regs);
+}
+
+static inline void __serial_putc(uart_t *uart, int handle, unsigned char c)
+{
+ if ( (c == '\n') && (handle & SERHND_COOKED) )
+ __serial_putc(uart, handle, '\r');
+
+ if ( handle & SERHND_HI )
+ c |= 0x80;
+ else if ( handle & SERHND_LO )
+ c &= ~0x7f;
+
+ while ( !(inb(uart->io_base + LSR) & LSR_THRE) )
+ barrier();
+
+ outb(c, uart->io_base + THR);
+}
+
+#define PARSE_ERR(_f, _a...) \
+ do { \
+ printk( "ERROR: " _f "\n" , ## _a ); \
+ DISABLE_UART(uart); \
+ return; \
+} while ( 0 )
+
+static void parse_port_config(char *conf, uart_t *uart)
+{
+ if ( *conf == '\0' )
+ return;
+
+ uart->baud = simple_strtol(conf, &conf, 10);
+ if ( (uart->baud < 1200) || (uart->baud > 115200) )
+ PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
+
+ if ( *conf != ',' )
+ PARSE_ERR("Missing data/parity/stop specifiers.");
+
+ conf++;
+
+ uart->data_bits = simple_strtol(conf, &conf, 10);
+ if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
+ PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
+
+ switch ( *conf )
+ {
+ case 'n':
+ uart->parity = PARITY_NONE;
+ break;
+ case 'o':
+ uart->parity = PARITY_ODD;
+ break;
+ case 'e':
+ uart->parity = PARITY_EVEN;
+ break;
+ case 'm':
+ uart->parity = PARITY_MARK;
+ break;
+ case 's':
+ uart->parity = PARITY_SPACE;
+ break;
+
+ default:
+ PARSE_ERR("Invalid parity specifier '%c'.", *conf);
+ }
+
+ conf++;
+
+ uart->stop_bits = simple_strtol(conf, &conf, 10);
+ if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
+ PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
+
+ if ( *conf == ',' )
+ {
+ conf++;
+
+ uart->io_base = simple_strtol(conf, &conf, 0);
+ if ( (uart->io_base <= 0x0000) || (uart->io_base > 0xfff0) )
+ PARSE_ERR("I/O port base 0x%x is outside the supported range.",
+ uart->io_base);
+
+ if ( *conf != ',' )
+ PARSE_ERR("Missing IRQ specifier.");
+
+ conf++;
+
+ uart->irq = simple_strtol(conf, &conf, 10);
+ if ( (uart->irq <= 0) || (uart->irq >= 32) )
+ PARSE_ERR("IRQ %d is outside the supported range.", uart->irq);
+ }
+}
+
+static void uart_config_stage1(uart_t *uart)
+{
+ unsigned char lcr;
+
+ if ( !UART_ENABLED(uart) )
+ return;
+
+ lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
+
+ /* No interrupts. */
+ outb(0, uart->io_base + IER);
+
+ /* Line control and baud-rate generator. */
+ outb(lcr | LCR_DLAB, uart->io_base + LCR);
+ outb(115200/uart->baud, uart->io_base + DLL); /* baud lo */
+ outb(0, uart->io_base + DLM); /* baud hi */
+ outb(lcr, uart->io_base + LCR); /* parity, data, stop */
+
+ /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
+ outb(MCR_DTR | MCR_RTS, uart->io_base + MCR);
+
+ /* Enable and clear the FIFOs. Set a large trigger threshold. */
+ outb(FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14, uart->io_base + FCR);
+}
+
+static void uart_config_stage2(uart_t *uart)
+{
+ int rc;
+
+ if ( !UART_ENABLED(uart) )
+ return;
+
+ rc = request_irq(uart->irq,
+ serial_interrupt,
+ SA_NOPROFILE,
+ "serial",
+ uart);
+ if ( rc != 0 )
+ printk("ERROR: Failed to allocate serial IRQ %d\n", uart->irq);
+
+ /* For sanity, clear the receive FIFO. */
+ outb(FCR_ENABLE | FCR_CLRX | FCR_TRG14, uart->io_base + FCR);
+
+ /* Master interrupt enable; also keep DTR/RTS asserted. */
+ outb(MCR_OUT2 | MCR_DTR | MCR_RTS, uart->io_base + MCR);
+
+ /* Enable receive interrupts. */
+ outb(IER_ERDAI, uart->io_base + IER);
+}
+
+
+/***********************
+ * PUBLIC FUNCTIONS
+ */
+
+void serial_init_stage1(void)
+{
+ extern unsigned char opt_com1[], opt_com2[];
+
+ parse_port_config(opt_com1, &com[0]);
+ parse_port_config(opt_com2, &com[1]);
+
+ uart_config_stage1(&com[0]);
+ uart_config_stage1(&com[1]);
+}
+
+void serial_init_stage2(void)
+{
+ uart_config_stage2(&com[0]);
+ uart_config_stage2(&com[1]);
+}
+
+int parse_serial_handle(char *conf)
+{
+ int handle;
+
+ /* Silently fail if user has explicitly requested no serial I/O. */
+ if ( strcmp(conf, "none") == 0 )
+ return -1;
+
+ if ( strncmp(conf, "com", 3) != 0 )
+ goto fail;
+
+ switch ( conf[3] )
+ {
+ case '1':
+ handle = 0;
+ break;
+ case '2':
+ handle = 1;
+ break;
+ default:
+ goto fail;
+ }
+
+ if ( !UART_ENABLED(&com[handle]) )
+ {
+ printk("ERROR: cannot use unconfigured serial port COM%d\n", handle+1);
+ return -1;
+ }
+
+ if ( conf[4] == 'H' )
+ handle |= SERHND_HI;
+ else if ( conf[4] == 'L' )
+ handle |= SERHND_LO;
+
+ handle |= SERHND_COOKED;
+
+ return handle;
+
+ fail:
+ printk("ERROR: bad serial-interface specification '%s'\n", conf);
+ return -1;
+}
+
+void serial_set_rx_handler(int handle, serial_rx_fn fn)
+{
+ uart_t *uart = &com[handle & SERHND_IDX];
+ unsigned long flags;
+
+ if ( handle == -1 )
+ return;
+
+ spin_lock_irqsave(&uart->lock, flags);
+
+ if ( uart->rx != NULL )
+ goto fail;
+
+ if ( handle & SERHND_LO )
+ {
+ if ( uart->rx_lo != NULL )
+ goto fail;
+ uart->rx_lo = fn;
+ }
+ else if ( handle & SERHND_HI )
+ {
+ if ( uart->rx_hi != NULL )
+ goto fail;
+ uart->rx_hi = fn;
+ }
+ else
+ {
+ if ( (uart->rx_hi != NULL) || (uart->rx_lo != NULL) )
+ goto fail;
+ uart->rx = fn;
+ }
+
+ spin_unlock_irqrestore(&uart->lock, flags);
+ return;
+
+ fail:
+ spin_unlock_irqrestore(&uart->lock, flags);
+ printk("ERROR: Conflicting receive handlers for COM%d\n",
+ handle & SERHND_IDX);
+}
+
+void serial_putc(int handle, unsigned char c)
+{
+ uart_t *uart = &com[handle & SERHND_IDX];
+ unsigned long flags;
+
+ if ( handle == -1 )
+ return;
+
+ spin_lock_irqsave(&uart->lock, flags);
+
+ __serial_putc(uart, handle, c);
+
+ spin_unlock_irqrestore(&uart->lock, flags);
+}
+
+void serial_puts(int handle, const unsigned char *s)
+{
+ uart_t *uart = &com[handle & SERHND_IDX];
+ unsigned long flags;
+
+ if ( handle == -1 )
+ return;
+
+ spin_lock_irqsave(&uart->lock, flags);
+
+ while ( *s != '\0' )
+ __serial_putc(uart, handle, *s++);
+
+ spin_unlock_irqrestore(&uart->lock, flags);
+}
+++ /dev/null
-#include <asm-i386/io.h>
-#include <xeno/sched.h> /* this has request_irq() proto for some reason */
-#include <xeno/keyhandler.h>
-#include <xeno/reboot.h>
-#include <xeno/irq.h>
-#include <asm/pdb.h>
-
-/* Register offsets */
-#define NS16550_RBR 0x00 /* receive buffer */
-#define NS16550_THR 0x00 /* transmit holding */
-#define NS16550_IER 0x01 /* interrupt enable */
-#define NS16550_IIR 0x02 /* interrupt identity */
-#define NS16550_FCR 0x02 /* FIFO control */
-#define NS16550_LCR 0x03 /* line control */
-#define NS16550_MCR 0x04 /* MODEM control */
-#define NS16550_LSR 0x05 /* line status */
-#define NS16550_MSR 0x06 /* MODEM status */
-#define NS16550_SCR 0x07 /* scratch */
-#define NS16550_DDL 0x00 /* divisor latch (ls) ( DLAB=1) */
-#define NS16550_DLM 0x01 /* divisor latch (ms) ( DLAB=1) */
-
-/* Interrupt enable register */
-#define NS16550_IER_ERDAI 0x01 /* rx data recv'd */
-#define NS16550_IER_ETHREI 0x02 /* tx reg. empty */
-#define NS16550_IER_ELSI 0x04 /* rx line status */
-#define NS16550_IER_EMSI 0x08 /* MODEM status */
-
-/* FIFO control register */
-#define NS16550_FCR_ENABLE 0x01 /* enable FIFO */
-#define NS16550_FCR_CLRX 0x02 /* clear Rx FIFO */
-#define NS16550_FCR_CLTX 0x04 /* clear Tx FIFO */
-#define NS16550_FCR_DMA 0x10 /* enter DMA mode */
-#define NS16550_FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */
-#define NS16550_FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */
-#define NS16550_FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
-#define NS16550_FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */
-
-/* MODEM control register */
-#define NS16550_MCR_DTR 0x01 /* Data Terminal Ready */
-#define NS16550_MCR_RTS 0x02 /* Request to Send */
-#define NS16550_MCR_OUT1 0x04 /* OUT1: unused */
-#define NS16550_MCR_OUT2 0x08 /* OUT2: interrupt mask */
-#define NS16550_MCR_LOOP 0x10 /* Loop */
-
-#define LSR_DR 0x01 /* Data ready */
-#define LSR_OE 0x02 /* Overrun */
-#define LSR_PE 0x04 /* Parity error */
-#define LSR_FE 0x08 /* Framing error */
-#define LSR_BI 0x10 /* Break */
-#define LSR_THRE 0x20 /* Xmit holding register empty */
-#define LSR_TEMT 0x40 /* Xmitter empty */
-#define LSR_ERR 0x80 /* Error */
-
-#define SERIAL_COM1 0x3f8
-#define SERIAL_COM2 0x2f8
-
-void initialize_serial_port(int base);
-
-int serial_com_base = SERIAL_COM1;
-int debug_com_base = SERIAL_COM1;
-
-static int serial_echo = 0; /* default is not to echo; change with '~' */
-
-void toggle_echo(u_char key, void *dev_id, struct pt_regs *regs)
-{
- serial_echo = !serial_echo;
-}
-
-void debug_set_com_port(int port)
-{
- debug_com_base = port == 1 ? SERIAL_COM1 : SERIAL_COM2;
- if (port == 2) initialize_serial_port(SERIAL_COM2);
-}
-
-int debug_testchar() /* character available? */
-{
- return (inb(debug_com_base + NS16550_LSR) & LSR_DR);
-}
-
-u_char debug_getchar()
-{
- while (! (inb(debug_com_base + NS16550_LSR) & LSR_DR));/* wait for char */
- return inb(debug_com_base + NS16550_RBR);
-}
-
-void debug_putch(u_char c)
-{
- while (! (inb(debug_com_base + NS16550_LSR) & LSR_THRE));
- /* wait for idle */
- outb(c, debug_com_base + NS16550_RBR);
-}
-
-void debug_putchar(u_char c)
-{
- debug_putch(c);
- if (c == '\n') debug_putch('\r');
-}
-
-
-
-int serial_testchar() /* character available? */
-{
- return (inb(serial_com_base + NS16550_LSR) & LSR_DR);
-}
-
-u_char serial_getchar()
-{
- while (! (inb(serial_com_base + NS16550_LSR) & LSR_DR));/* wait for char */
- return inb(serial_com_base + NS16550_RBR);
-}
-
-void serial_putch(u_char c)
-{
- while (! (inb(serial_com_base + NS16550_LSR) & LSR_THRE));
- /* wait for idle */
- outb(c, serial_com_base + NS16550_RBR);
-}
-
-void serial_putchar(u_char c)
-{
- serial_putch(c);
- if ( c == '\n' )
- serial_putch('\r');
-}
-
-static spinlock_t serial_lock;
-
-static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- u_char c;
- key_handler *handler;
- unsigned long flags;
-
- spin_lock_irqsave(&serial_lock, flags);
-
- while ( serial_testchar() )
- {
- c = serial_getchar();
-
- if ( c & 0x80 )
- {
- pdb_serial_input(c & 0x7f, regs);
- }
- else
- {
- if ( (handler = get_key_handler(c)) != NULL )
- (*handler)(c, dev_id, regs);
-
- if ( serial_echo )
- serial_putch(c);
- }
- }
-
- spin_unlock_irqrestore(&serial_lock, flags);
-}
-
-void initialize_serial()
-{
- if ( !SERIAL_ENABLED )
- return;
-
- spin_lock_init(&serial_lock);
-
- /* setup key handler */
- add_key_handler('~', toggle_echo, "toggle serial echo");
-
- initialize_serial_port(SERIAL_COM1);
-}
-
-/* warning: no protection against duplicate initialization */
-void initialize_serial_port(int base)
-{
- int rc;
-
- /* This assumes we have a 16550. It's pretty darned likely really! */
- /* Clear FIFOs, enable, trigger at 1 byte */
- outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
- NS16550_FCR_CLRX | NS16550_FCR_CLTX,
- base + NS16550_FCR);
-
- /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */
- outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS,
- base + NS16550_MCR);
- outb(NS16550_IER_ERDAI,
- base + NS16550_IER );
-
- switch(base)
- {
- case SERIAL_COM1 :
- {
- if( (rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial 1", 0)) )
- printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc);
- break;
- }
- case SERIAL_COM2 :
- {
- if( (rc = request_irq(3, serial_rx_int, SA_NOPROFILE, "serial 2", 0)) )
- printk("initialize_serial: failed to get IRQ3, rc=%d\n", rc);
- break;
- }
- default :
- {
- printk("initialize_serial: unknown serial base: 0x%d\n", base);
- }
- }
-}
#ifndef NDEBUG
#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \
- __FILE__, __LINE__, ## _a)
+ __FILE__ , __LINE__ , ## _a )
#define STACK_GUARD
#else
#define DPRINTK(_f, _a...) ((void)0)
* who gets the PS/2 keyboard/mouse events
*/
+extern int sercon_handle;
+extern int vgacon_enabled;
+
#define CONSOLE_ISOWNER(p) (p->domain == 0)
#define CONSOLE_OWNER (find_domain_by_id(0))
-
-/*
- * Xen output redirection (in common/kernel.c)
- *
- * This is coarsely done right now -
- * - a boot-time option for console output
- * - a compile-time option for serial output and console output
- *
- * Really, when starting up a guest os with console privilege, we should:
- * - reset the video to a known state
- * - stop sending characters (clear 'opt_console')
- * - allow the guest os access to the video RAM area and keyboard
- * Similarly, when stopping that guest os, we should:
- * - stop allowing the guest os access to video RAM
- * - reset the video to a known state
- * - start sending it console output again (if we so desire)
- *
- * Resetting the video to a known state has not been explored yet, although
- * Xen resets to a VGA text mode at start of day. Also, the notion of
- * privileges for guest os's (e.g. console privilege) has not been explored
- * yet, so this will do for now.
- */
-
-#define CONFIG_OUTPUT_SERIAL 1
-#define CONFIG_OUTPUT_CONSOLE 1
-#define CONFIG_OUTPUT_CONSOLE_RING 1
-
-extern int opt_console;
-
#define CONSOLE_RING_SIZE 16392
#define CONSOLE_RING_CLEAR 1
/* kernel.c */
#define printk printf
void printf (const char *format, ...);
-void cls(void);
void panic(const char *format, ...);
/* vsprintf.c */
--- /dev/null
+/******************************************************************************
+ * serial.h
+ *
+ * Driver for 16550-series UARTs. This driver is to be kept within Xen as
+ * it permits debugging of seriously-toasted machines (e.g., in situations
+ * where a device driver within a guest OS would be inaccessible).
+ *
+ * Copyright (c) 2003-2004, K A Fraser
+ */
+
+#ifndef __XEN_SERIAL_H__
+#define __XEN_SERIAL_H__
+
+#include <asm/ptrace.h>
+
+/* 'Serial handles' are comprise the following fields. */
+#define SERHND_IDX (1<<0) /* COM1 or COM2? */
+#define SERHND_HI (1<<1) /* Mux/demux each transferred char by MSB. */
+#define SERHND_LO (1<<2) /* Ditto, except that the MSB is cleared. */
+#define SERHND_COOKED (1<<3) /* Newline/carriage-return translation? */
+
+/* Two-stage initialisation (before/after IRQ-subsystem initialisation). */
+void serial_init_stage1(void);
+void serial_init_stage2(void);
+
+/* Takes a config string and creates a numeric handle on the COM port. */
+int parse_serial_handle(char *conf);
+
+/* Register a character-receive hook on the specified COM port. */
+typedef void (*serial_rx_fn)(unsigned char, struct pt_regs *);
+void serial_set_rx_handler(int handle, serial_rx_fn fn);
+
+/* Transmit a single character via the specified COM port. */
+void serial_putc(int handle, unsigned char c);
+
+/* Transmit a NULL-terminated string via the specified COM port. */
+void serial_puts(int handle, const unsigned char *s);
+
+#endif /* __XEN_SERIAL_H__ */